Class Tetris extends Box
var structs;
var map;
var panel;
var preview;
var levelLabel;
var linesLabel;
var pauseButton;
var dir;
var index;
var index2;
var nextIndex;
var downTime;
var duration=300;
var pressPos;
var eliminates;
function Tetris(){
	this.structs=[
		[[11,12,21,22]],
		[[1,11,21,31],[10,11,12,13]],
		[[1,11,12,22],[10,11,1,2]],
		[[2,11,12,21],[12,11,1,0]],
		[[1,10,11,12],[10,21,11,1],[21,12,11,10],[12,1,11,21]],
		[[2,1,11,21],[0,10,11,12],[20,21,11,1],[22,12,11,10]],
		[[0,1,11,21],[20,10,11,12],[22,21,11,1],[2,12,11,10]],
	];
	G.main.addChild(this);
	this.set({pos:[0,0,"f","f"],bg:"#fff"});
	this.addChild([
		[{dim:"map",pos:[0,"b",500,1000]}],
		[{dim:"panel",pos:[500,0,"f-500","f"],bg:["#e8e8e8",[,,"2#666"]]},
			[{pos:[0,120,"f",250],bg:["#d8d8d8",["2#666","2#666"]]}],
			[Button,{dim:"pauseButton",subEnabled:false,pos:[0,0,"f",120],type:3,bg:"#e8e8e8"},
				[{pos:["c-15","c",12,42],bg:"#888"}],
				[{pos:["c+15","c",12,42],bg:"#888"}],
			],
			[{dim:"preview",y:120}],
			[["LEVEL","#888",30],{pos:[0,420,"f"],align:"c"}],
			[["1","#444",30],{dim:"levelLabel",pos:[0,470,"f"],align:"c"}],
			[["LINES","#888",30],{pos:[0,570,"f"],align:"c"}],
			[["0","#444",30],{dim:"linesLabel",pos:[0,620,"f"],align:"c"}],
		],
		[new Label("Pause","#fff",90),{dim:"cover",visible:false,bold:true,enabled:true,pos:[0,0,"f","f"],bg:"#6000",align:"c",lineH:G.h}]
	]);
	if(G.main.h<1000){
		var scale=G.main.h/1000;
		this.map.setScaleY(scale);
		this.map.setY(0);
	}
	this.start();
	this.playTime();
}
function start(){
	this.lastDownTime=G.now;
	this.nextIndex=1;
	this.duration=300;
	this.linesLabel.setText(0);
	this.map.removeChildren();
	this.createTile();
}
function createTile(){
	this.index=this.nextIndex;
	this.index2=0;
	this.nextIndex=int(Math.random()*this.structs.length);
	this.preview.removeChildren();
	var index=this.nextIndex;
	var arr=this.structs[index][0];
	for(var i=0;i<arr.length;i++){
		var n=arr[i];
		var tile=this.preview.addChild({w:28,h:28,bg:["#fff","#666"]});
		tile.setPos((n%10)*30,int(n/10)*30);
	}
	var w=(index==1||index==4?3:(index==6?2:4))*30;
	var h=(index>=2?3:4)*30;
	this.preview.setPos((G.w-500-w)/2,(250-h)/2+120);

	arr=this.structs[this.index][0];
	var diff=this.index==1?0:(this.index==4?2:1);
	for(var i=0;i<arr.length;i++){
		var n=arr[i];
		var tile=this.map.addChild({w:48,h:48,bg:["#fff","#666"]});
		tile.set({index:i,place:0,toPlace:0,fixed:false});
		this.setPlace(tile,(Math.abs(int(n/10))+diff)*100+(n%10+7));
	}
}
function getTile(place){
	for(var i=0;i<this.map.children.length;i++){
		var tile=this.map.children[i];
		if(tile.fixed&&tile.place==place) return tile;
	}
	return null;
}
function setPlace(tile,place){
	tile.place=place;
	tile.setPos((place%100-4)*50,(int(place/100)-4)*50);
}
function move(dir){
	if(this.duration==0) return;
	var canMove=this.testMove(dir,true);
	if(dir==2){
		if(!canMove){
			this.moveEnd();
		}
	}
}
function moveEnd(step=1){
	if(step==1){
		this.duration=0;
		this.eliminates=[];
		var rowHash={};
		var isLose=false;
		for(var i=0;i<this.map.children.length;i++){
			var tile=this.map.children[i];
			if(!tile.fixed){
				tile.fixed=true;
				tile.setBg(["#d8d8d8","#666"]);
			}
			var row=int(tile.place/100);
			if(!rowHash[row]) rowHash[row]=0;
			rowHash[row]++;
			if(rowHash[row]==10) this.eliminates.push(row);
			if(row<4) isLose=true;
		}
		if(isLose){
			new DlgAlert("You lose!\n\nClick button to continue.",[this,this.start]);
		}
		else if(this.eliminates.length==0){
			this.moveEnd(7);
		}
		else{
			this.moveEnd(2);
		}
	}
	else if(step<6){
		for(var i=0;i<this.map.children.length;i++){
			var tile=this.map.children[i];
			if(this.eliminates.indexOf(int(tile.place/100))>-1){
				tile.setBg([step%2==1?"#d8d8d8":"#fff","#666"]);
			}
		}
		callLater([this,this.moveEnd,step+1],200);
	}
	else if(step==6){
		for(var i=this.map.children.length-1;i>=0;i--){
			var tile=this.map.children[i];
			if(this.eliminates.indexOf(int(tile.place/100))>-1){
				tile.remove();
			}
			else{
				var row=int(tile.place/100);
				for(var j=0;j<this.eliminates.length;j++){
					if(row<this.eliminates[j]) row++;
				}
				this.setPlace(tile,row*100+tile.place%100);
			}
		}
		this.moveEnd(7);
	}
	else if(step==7){
		this.linesLabel.setText(int(this.linesLabel.text)+Math.pow(this.eliminates.length,2));
		this.duration=300;
		this.pressPos=null;
		this.createTile();
	}
}
function testMove(dir,isDo=false){
	var canMove=true;
	var toIndex2=this.index2;
	if(dir==1){
		toIndex2++;
		var arr=this.structs[this.index];
		if(toIndex2>=arr.length) toIndex2=0;
	}
	for(var i=0;i<this.map.children.length;i++){
		var tile=this.map.children[i];
		if(tile.fixed) continue;
		tile.toPlace=tile.place;
		if(dir==1){
			var arr=this.structs[this.index];
			var n1=arr[this.index2][tile.index];
			var n2=arr[toIndex2][tile.index];
			tile.toPlace=(int(tile.place/100)+int(n2/10)-int(n1/10))*100;
			tile.toPlace+=tile.place%100+n2%10-n1%10;
		}
		if(dir==2) tile.toPlace+=100;
		if(dir==3) tile.toPlace-=1;
		if(dir==4) tile.toPlace+=1;
		if(tile.toPlace%100<4||tile.toPlace%100>=14) canMove=false;
		if(int(tile.toPlace/100)>=24) canMove=false;
		if(canMove&&this.getTile(tile.toPlace)) canMove=false;
		if(!canMove) break;
	}
	for(var i=0;i<this.map.children.length;i++){
		var tile=this.map.children[i];
		if(tile.fixed) continue;
		if(canMove&&isDo){
			this.setPlace(tile,tile.toPlace);
		}
	}
	if(dir==1&&canMove) this.index2=toIndex2;
	return canMove;
}
function onPress(){
	this.dir=0;
	if(G.target!=this.pauseButton&&G.target!=this.cover){
		this.pressPos=[G.x,G.y];
	}
}
function onRelease(){
	this.dir=0;
	this.pressPos=null;
}
function onClick(){
	if(G.target==this.cover){
		this.cover.transit({alpha:0},[this.cover,this.cover.setVisible,false]);
		this.duration=300;
	}
	else if(G.target!=this.pauseButton){
		this.move(1);
	}
}
function onButtonClick(){
	if(G.target==this.pauseButton){
		this.cover.setVisible(true);
		this.cover.transit({alpha:[0,1]});
		this.duration=0;
	}
}
function playTime(){
	callLater([this,this.playTime]);
	if(!G.main.enabled) return;
	if(G.now-this.downTime>=this.duration){
		this.downTime=G.now;
		this.move(2);
	}
	if(this.pressPos){
		var dir=0;
		if(G.x<this.pressPos[0]-50) dir=3;
		if(G.x>this.pressPos[0]+50) dir=4;
		if(G.y>this.pressPos[1]+100) dir=2;
		if(dir>0&&(this.dir==0||this.dir==dir)){
			this.dir=dir;
			if(dir==2){
				this.duration=1;
			}
			else{
				this.downTime+=50;
				this.move(dir);
			}
			this.pressPos[0]=G.x;
			this.pressPos[1]=G.y;
		}
	}
}